Android Логика создания сеанса Camera2 - PullRequest
1 голос
/ 06 мая 2020

Я новичок в платформе Camera2 и пытаюсь понять лог c создания сессий захвата.

Мне нужна простая вещь - предварительный просмотр и запись видео. Я также хочу установить правильную подсказку ориентации в то время, когда я начинаю запись видео . Но у меня возникла проблема с курицей / яйцом.

Вот мой лог c:

Чтобы начать запись, я делаю это:

    val recordRequest = session.device.createCaptureRequest(CameraDevice.TEMPLATE_RECORD).apply {
        // Add the preview and recording surface targets
        addTarget(viewFinder.holder.surface)
        addTarget(recorder.surface)
    }.build()

    session.setRepeatingRequest(recordRequest, null, cameraHandler)

    recorder.setOrientationHint(it) // NOT allowed after getSurface()!
    recorder.prepare()              // NOT allowed after getSurface()!
    recorder.start()

Однако я уже набрал recorder.surface (или getSurface()), когда добавил цели выше. Можно подумать, что я могу подготовить, а затем добавить цели, однако документация для addTarget() говорит, что поверхность Добавленная поверхность должна быть одной из поверхностей, включенных в самый последний вызов CameraDevice # createCaptureSession


Это приводит к интересной проблеме. Каждый раз, когда я открываю приложение, мне нужно создать сеанс захвата, чтобы начать предварительный просмотр изображения с камеры. Однако в момент создания createCaptureSession () необходимо включить все поверхности , которые появятся в будущем запросы захвата . Это означает, что мне также нужно включить поверхность для записи, даже если я просто открою камеру без записи. Как мне получить эту Surface для записи? Что ж, в документации написано, что я могу получить его от MediaRecorder или от MediaCodec. Я хочу получить его из MediaRecorder, так как хочу использовать CamcorderProfiles. Однако, как я показал в приведенном выше коде, как только я получаю поверхность от рекордера в точке создания сеанса - я не могу делать никаких изменений там в точке начала записи , например, установка подсказки ориентации.

Официальный образец приложения Camera2Video делает трюк - он использует createPersistentInputSurface , однако в их примере камера фиксирована, что позволяет им выделять достаточно память для него и использовать эту поверхность на протяжении всего жизненного цикла приложения.

Как это можно решить? Я неправильно понимаю концепции здесь? Как я могу создать рекордер позже, когда я начинаю запись, но при этом поверхность для него создается ранее, когда я открываю камеру для предварительного просмотра?

1 Ответ

2 голосов
/ 07 мая 2020

Использование постоянной поверхности ввода - правильный подход. Создайте новый MediaRecorder, когда вы знаете ориентацию для записи, и установите его Surface, используя постоянную поверхность ввода.

Это именно то, что делает пример Camera2Video, также :

        // React to user touching the capture button
        capture_button.setOnTouchListener { view, event ->
            when (event.action) {

                MotionEvent.ACTION_DOWN -> lifecycleScope.launch(Dispatchers.IO) {

                    // Prevents screen rotation during the video recording
                    requireActivity().requestedOrientation =
                            ActivityInfo.SCREEN_ORIENTATION_LOCKED

                    // Start recording repeating requests, which will stop the ongoing preview
                    //  repeating requests without having to explicitly call `session.stopRepeating`
                    session.setRepeatingRequest(recordRequest, null, cameraHandler)

                    // Finalizes recorder setup and starts recording
                    recorder.apply {
                        // Sets output orientation based on current sensor value at start time
                        relativeOrientation.value?.let { setOrientationHint(it) }
                        prepare()
                        start()
                    }

и recorder создается с помощью ранее созданной постоянной поверхности:

    /** Saves the video recording */
    private val recorder: MediaRecorder by lazy { createRecorder(recorderSurface) 
    }

Когда вы говорите, что камера зафиксирована, вы имеете в виду, что ориентация приложения фиксирована, или что образец не t поддержка переключения передней / задней камеры? Ничто из этого не должно иметь особого значения для стойких поверхностей; при необходимости вы можете создать новую, когда переключаете камеры или меняете ориентацию.

...