Arhn - архитектура программирования

Как записывать отфильтрованные видеокадры с помощью MediaRecorder и OpenGL ES

Я пытаюсь создать приложение камеры, которое должно иметь возможность фильтровать кадры с примененным к нему фильтром (только для целей обучения). Для этого я использовал Camera2 API и OpenGL ES. Мне удалось применить фильтр оттенков серого к кадрам, чтобы предварительный просмотр был в оттенках серого. Теперь я хотел записать этот отфильтрованный предварительный просмотр с помощью MediaRecorder и просмотрел следующее sample, чтобы увидеть, как MediaRecorder работает с Camera2 API (я только что добавил часть OpenGL ES). Но когда я записываю, он записывает предварительный просмотр без фильтра, а не отфильтрованный предварительный просмотр. Здесь демонстрация. Вот как выглядит предварительный просмотр камеры при включенном фильтре оттенков серого:

введите здесь описание изображения

А вот как это выглядит при воспроизведении записанного видео после его сохранения в каталоге:

введите здесь описание изображения

Мне кажется, что MediaRecorder просто берет нефильтрованные/необработанные кадры и сохраняет их.

Вот соответствующие части моего кода:

// basically the same code from the link above
// here: mSurfaceTexture is the surface texture I created via glGenTextures()
public void startRecordingVideo() {
        if (null == mCameraDevice || null == mCameraSize) {
            return;
        }


        try {
            closePreviewSession();
            setUpMediaRecorder();
            SurfaceTexture texture = mSurfaceTexture;
            assert texture != null;
            texture.setDefaultBufferSize(mCameraSize.getWidth(), mCameraSize.getHeight());
            mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            List<Surface> surfaces = new ArrayList<>();

            // Set up Surface for the camera preview
            Surface previewSurface = new Surface(texture);
            surfaces.add(previewSurface);
            mCaptureRequestBuilder.addTarget(previewSurface);

            // Set up Surface for the MediaRecorder
            Surface recorderSurface = mMediaRecorder.getSurface();
            surfaces.add(recorderSurface);
            mCaptureRequestBuilder.addTarget(recorderSurface);

            // Start a capture session
            // Once the session starts, we can update the UI and start recording
            mCameraDevice.createCaptureSession(surfaces, mCameraCaptureSessionCallbackForTemplateRecord , mBackgroundHandler);
        } catch (CameraAccessException | IOException e) {
            e.printStackTrace();
        }

    }

Часть MediaRecorder также взята из примера выше:

private void setUpMediaRecorder() throws IOException {
        final Activity activity = mActivity;
        if (null == activity) {
            return;
        }

        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        if (mNextVideoAbsolutePath == null || mNextVideoAbsolutePath.isEmpty()) {
            mNextVideoAbsolutePath = getVideoFilePath(mActivity);
        }
        mMediaRecorder.setOutputFile(mNextVideoAbsolutePath);
        mMediaRecorder.setVideoEncodingBitRate(10000000);
        mMediaRecorder.setVideoFrameRate(30);
        mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        switch (mSensorOrientation) {
            case SENSOR_ORIENTATION_DEFAULT_DEGREES:
                mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
                break;
            case SENSOR_ORIENTATION_INVERSE_DEGREES:
                mMediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
                break;
        }
        mMediaRecorder.prepare();
    }

Итак, как я могу указать MediaRecorder использовать отфильтрованные/обработанные кадры? Это возможно ?

Я попытался вызвать setInputSurface() в экземпляре MediaRecorder, передав ему переменную previewSurface (до этого я преобразовал эту переменную в глобальную переменной, чтобы я мог использовать ее и в методе setUpMediaRecorder()). Но я получил ошибку, указывающую, что это не постоянная поверхность. В документе для setInputSurface() указано, что следует использовать постоянную поверхность (что бы это ни значило)

Я надеюсь, что кто-то может помочь ?


  • Я в таком же положении. 14.10.2019
  • Привет, парень, я на том же этапе. У кого-нибудь из вас получилось? 31.03.2020

Ответы:


1

Вы не можете использовать MediaRecorder для работы с таким потоком, потому что он может либо работать с вводом с одной камеры (и вы не имеете контроля над записью, пока не остановите ее), либо записывать Surface.

Ну, в принципе, вы можете получать цветные кадры с камеры, конвертировать их в оттенки серого, рисовать результат на Surface и подключать этот Surface к MediaRecorder, подобно тому, как Camera2Video реализует замедленную запись.

Гораздо лучше сжать кадры в градациях серого с помощью библиотеки MediaCodec и сохранить полученные закодированные кадры в видеофайле с помощью библиотеки MediaMuxer, подобно запись с камеры.

06.10.2020
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..