Воспроизведение видео с OpenGL и MediaCodec

Я пытаюсь воспроизвести одно и то же видео одновременно в двух разных видах текстур. Я использовал код от grafika (MoviePlayer и ContinuousCaptureActivity), чтобы попытаться заставить его работать (спасибо, fadden). Чтобы упростить задачу, я пытаюсь сделать это сначала одним TextureView.

На данный момент я создал TextureView, и как только он получит SurfaceTexture, я создаю WindowSurface и делаю его текущим. Затем я генерирую TextureID, сгенерированный с использованием объекта FullFrameRect.

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int
        width, int height) {
    mSurfaceTexture = surface;
    mEGLCore = new EglCore(null, EglCore.FLAG_TRY_GLES3);
    Log.d("EglCore", "EGL core made");
    mDisplaySurface = new WindowSurface(mEGLCore, mSurfaceTexture);
    mDisplaySurface.makeCurrent();
    Log.d("DisplaySurface", "mDisplaySurface made");
    mFullFrameBlit = new FullFrameRect(new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT));
    mTextureID = mFullFrameBlit.createTextureObject();

    //mSurfaceTexture.attachToGLContext(mTextureID);
    clickPlayStop(null);
}

Затем я получаю внеэкранную SurfaceTexture, связываю ее с TextureID, который я получил выше, и создаю поверхность для передачи в MoviePlayer таким образом:

public void clickPlayStop(@SuppressWarnings("unused") View unused) {
    if (mShowStopLabel) {
        Log.d(TAG, "stopping movie");
        stopPlayback();
        // Don't update the controls here -- let the task thread do it after the movie has
        // actually stopped.
        //mShowStopLabel = false;
        //updateControls();
    } else {
        if (mPlayTask != null) {
            Log.w(TAG, "movie already playing");
            return;
        }
        Log.d(TAG, "starting movie");
        SpeedControlCallback callback = new SpeedControlCallback();
        callback.setFixedPlaybackRate(24);

        MoviePlayer player = null;
        MovieTexture = new SurfaceTexture(mTextureID);
        MovieTexture.setOnFrameAvailableListener(this);
        Surface surface = new Surface(MovieTexture);
        try {
            player = new MoviePlayer(surface, callback, this);//TODO
        } catch (IOException ioe) {
            Log.e(TAG, "Unable to play movie", ioe);

            return;
        }

        adjustAspectRatio(player.getVideoWidth(), player.getVideoHeight());

        mPlayTask = new MoviePlayer.PlayTask(player, this);
        mPlayTask.setLoopMode(true);


        mShowStopLabel = true;
        mPlayTask.execute();
    }
}

Идея состоит в том, что SurfaceTexture получает необработанный кадр, который я могу использовать в качестве текстуры OES_external для выборки из OpenGL. Затем я могу вызвать DrawFrame() из моего EGLContext после установки моего WindowSurface как текущего.

private void drawFrame() {
    Log.d(TAG, "drawFrame");
    if (mEGLCore == null) {
        Log.d(TAG, "Skipping drawFrame after shutdown");
        return;
    }

    // Latch the next frame from the camera.
    mDisplaySurface.makeCurrent();
    MovieTexture.updateTexImage();
    MovieTexture.getTransformMatrix(mTransformMatrix);

    // Fill the WindowSurface with it.
    int viewWidth = mTextureView.getWidth();
    int viewHeight = mTextureView.getHeight();
    GLES20.glViewport(0, 0, viewWidth, viewHeight);
    mFullFrameBlit.drawFrame(mTextureID, mTransformMatrix);
    mDisplaySurface.swapBuffers();
}

Если бы я хотел сделать это с двумя TextureView, идея состояла бы в том, чтобы вызвать makeCurrent() и рисовать в каждом буфере для каждого представления, а затем вызывать swapBuffers() после завершения рисования.

Это то, что я хочу сделать, но я уверен, что это не то, что на самом деле делает мой код. Может ли кто-нибудь помочь мне понять, что мне нужно изменить, чтобы это работало?

@Fadden

Обновление: это интересно. Я изменил код в onSurfaceTextureAvailable для этого:

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int
        width, int height) {
    mSurfaceTexture = surface;
    TextureHeight = height;
    TextureWidth = width;
    //mEGLCore = new EglCore(null, EglCore.FLAG_TRY_GLES3);
    Log.d("EglCore", "EGL core made");
    //mDisplaySurface = new WindowSurface(mEGLCore, mSurfaceTexture);
    //mDisplaySurface.makeCurrent();
    Log.d("DisplaySurface", "mDisplaySurface made");
    //mFullFrameBlit = new FullFrameRect(new Texture2dProgram(Texture2dProgram.ProgramType.OPENGL_TEST));
    //mTextureID = mFullFrameBlit.createTextureObject();
    //clickPlayStop(null);


    // Fill the SurfaceView with it.
    //int viewWidth = width;
    //int viewHeight = height;
    //GLES20.glViewport(0, 0, viewWidth, viewHeight);
    //mFullFrameBlit.drawFrame(mTextureID, mTransformMatrix);
    //mFullFrameBlit.openGLTest();
    //mFullFrameBlit.testDraw(mDisplaySurface.getHeight(),mDisplaySurface.getWidth());
    //mDisplaySurface.swapBuffers();
}

Так что, это не должно вызывать ничего другого, просто показать пустой TextureView - и это то, что я вижу...

Пустой TextureView

1 ответ

Спасибо Фаддену за помощь.

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

Другие вопросы по тегам