I am using ExoPlayer as follows:
import androidx.media3.exoplayer.ExoPlayer;
I am attempting to use SurfaceTexture to retrieve video frames from ExoPlayer and render them in openGL ES. However, after playing the video for a while or when switching videos, the playback automatically stops. I have attempted error handling using onPlayerError, but no exceptions are being caught. Instead, I have noticed the following exception in my Logcat:
E/ExoPlayerImplInternal: Disable failed.
java.lang.IllegalStateException
at android.media.MediaCodec.native_flush(Native Method)
at android.media.MediaCodec.flush(MediaCodec.java:2388)
at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.flushOrReleaseCodec(MediaCodecRenderer.java:773)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.flushOrReleaseCodec(MediaCodecVideoRenderer.java:724)
at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onDisabled(MediaCodecRenderer.java:634)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onDisabled(MediaCodecVideoRenderer.java:569)
at com.google.android.exoplayer2.BaseRenderer.disable(BaseRenderer.java:168)
at com.google.android.exoplayer2.ExoPlayerImplInternal.disableRenderer(ExoPlayerImplInternal.java:1136)
at com.google.android.exoplayer2.ExoPlayerImplInternal.resetInternal(ExoPlayerImplInternal.java:891)
at com.google.android.exoplayer2.ExoPlayerImplInternal.releaseInternal(ExoPlayerImplInternal.java:864)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:373)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loopOnce(Looper.java:240)
at android.os.Looper.loop(Looper.java:351)
at android.os.HandlerThread.run(HandlerThread.java:67)
E/ExoPlayerImplInternal: Reset failed.
java.lang.IllegalStateException
at android.media.MediaCodec.native_stop(Native Method)
at android.media.MediaCodec.stop(MediaCodec.java:2338)
at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.releaseCodec(MediaCodecRenderer.java:668)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.releaseCodec(MediaCodecVideoRenderer.java:714)
at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onReset(MediaCodecRenderer.java:641)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onReset(MediaCodecVideoRenderer.java:578)
at com.google.android.exoplayer2.BaseRenderer.reset(BaseRenderer.java:175)
at com.google.android.exoplayer2.ExoPlayerImplInternal.resetInternal(ExoPlayerImplInternal.java:900)
at com.google.android.exoplayer2.ExoPlayerImplInternal.releaseInternal(ExoPlayerImplInternal.java:864)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:373)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loopOnce(Looper.java:240)
at android.os.Looper.loop(Looper.java:351)
at android.os.HandlerThread.run(HandlerThread.java:67)
I don't know what attempts to make that would be helpful in this case. Here is my code snippet:
In the onSurfaceCreated method, I create and bind the frame texture:
mVideoTextureId = TextureUtil.genTextureObj();
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mVideoTextureId);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
GLES20.GL_LINEAR);
mVideoSurfaceTexture = new SurfaceTexture(mVideoTextureId);
mVideoSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
mVideoFrameAvailable = true;
}
});
mVideoSurface = new Surface(mVideoSurfaceTexture);
In the onDrawFrame method, I update the video frames:
if (mVideoFrameAvailable) {
synchronized (this) {
mVideoSurfaceTexture.updateTexImage();
mVideoSurfaceTexture.getTransformMatrix(mVideoSTMatrix);
mVideoFrameAvailable = false;
}
}
I have also exposed a method externally, which is used to set my video file and display position:
public void setVideoPath(String videoPath, RectF normalCropRectF) {
if (!Objects.isNull(normalCropRectF)) {
mNormalCropRectF = normalCropRectF;
convertToGL(mNormalCropRectF, true);
}
try {
if (!Objects.isNull(mExoplayer)) {
mExoplayer.clearVideoSurface();
mExoplayer.setPlayWhenReady(false);
mExoplayer.release();
mExoplayer = null;
}
mExoplayer = new ExoPlayer.Builder(mContext).build();
mExoplayer.setVideoSurface(mVideoSurface);
mExoplayer.setVolume(0);
mExoplayer.setRepeatMode(Player.REPEAT_MODE_ALL);
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(String.valueOf(new File(videoPath).toURI())));
mExoplayer.setMediaItem(mediaItem);
mExoplayer.prepare();
mExoplayer.setPlayWhenReady(true);
mExoplayer.addListener(new Player.Listener() {
@Override
public void onPlaybackStateChanged(int playbackState) {
Player.Listener.super.onPlaybackStateChanged(playbackState);
switch (playbackState) {
case Player.STATE_READY:
if (!Objects.isNull(mRenderCommonCallbackImpl)) {
mRenderCommonCallbackImpl.startPlay();
}
break;
}
}
@Override
public void onPlayerError(PlaybackException error) {
Player.Listener.super.onPlayerError(error);
Log.d("=====", "error : " + error.getMessage());
}
@Override
public void onVideoSizeChanged(VideoSize videoSize) {
Player.Listener.super.onVideoSizeChanged(videoSize);
updateProjection(videoSize.width, videoSize.height);
}
});
} catch (Exception e) {
}
}
Any help or guidance on this issue would be greatly appreciated. I have provided the relevant code snippets and exception details above. If anyone has encountered a similar problem or has insights into why the ExoPlayer stops automatically during video playback, I would be grateful for your input. Thank you in advance for your time and assistance.