Воспроизведение видео с 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 - и это то, что я вижу...
1 ответ
Спасибо Фаддену за помощь.
Так что, похоже, возникла неизвестная проблема, которая была решена, когда я использовал новый поток для декодирования и создания кадров. Я не выяснил, что вызвало первоначальную проблему, но я нашел способ обойти это.