我想使用
我还想在录制时使用OpenGL处理帧。
之后,我使用Grafika的ContinuousCaptureActivity示例代码初始化EGL渲染上下文,创建
然后从我们的
接下来(像Grafika示例中一样处理帧),开始录制(
但是,如果启用了音频录制,则……
MediaRecorder
来录制视频,而不是使用MediaCodec
,因为我们知道MediaRecorder
非常易于使用。我还想在录制时使用OpenGL处理帧。
之后,我使用Grafika的ContinuousCaptureActivity示例代码初始化EGL渲染上下文,创建
cameraTexture
并将其作为Surface
传递给Camera2 API,如下链接代码https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/ContinuousCaptureActivity.java#L392。然后从我们的
recorderSurface
创建EGLSurface encodeSurface
,如下链接代码https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/ContinuousCaptureActivity.java#L418。接下来(像Grafika示例中一样处理帧),开始录制(
MediaRecorder.start()
),如果没有设置音频源,则能够成功录制视频。但是,如果启用了音频录制,则……
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC)
...
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
最终视频时长很长,无法正常播放。因此,当使用 Surface 作为输入并使用 GLES 来添加和处理帧时,MediaRecorder 音频编码器会破坏一切。
我不知道该如何修复它。
以下是我的代码用于处理帧(基于 Grafika 示例,几乎相同):
class GLCameraFramesRender(
private val width: Int,
private val height: Int,
private val callback: Callback,
recorderSurface: Surface,
eglCore: EglCore
) : OnFrameAvailableListener {
private val fullFrameBlit: FullFrameRect
private val textureId: Int
private val encoderSurface: WindowSurface
private val tmpMatrix = FloatArray(16)
private val cameraTexture: SurfaceTexture
val cameraSurface: Surface
init {
encoderSurface = WindowSurface(eglCore, recorderSurface, true)
encoderSurface.makeCurrent()
fullFrameBlit = FullFrameRect(Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT))
textureId = fullFrameBlit.createTextureObject()
cameraTexture = SurfaceTexture(textureId)
cameraSurface = Surface(cameraTexture)
cameraTexture.setOnFrameAvailableListener(this)
}
fun release() {
cameraTexture.setOnFrameAvailableListener(null)
cameraTexture.release()
cameraSurface.release()
fullFrameBlit.release(false)
eglCore.release()
}
override fun onFrameAvailable(surfaceTexture: SurfaceTexture) {
if (callback.isRecording()) {
drawFrame()
} else {
cameraTexture.updateTexImage()
}
}
private fun drawFrame() {
cameraTexture.updateTexImage()
cameraTexture.getTransformMatrix(tmpMatrix)
GLES20.glViewport(0, 0, width, height)
fullFrameBlit.drawFrame(textureId, tmpMatrix)
encoderSurface.setPresentationTime(cameraTexture.timestamp)
encoderSurface.swapBuffers()
}
interface Callback {
fun isRecording(): Boolean
}
}