The following code works when I load all bitmaps beforehand (with testing data)
for (bitmap in bitmaps){
feedInOpenGL(bitmap)
}
But when I try to create the bitmap using a timer,
timer!!.scheduleAtFixedRate(object : TimerTask() {
override fun run() {
if (!recording) return
val bitmap = getNextBitmap()
feedInOpenGL(bitmap)
}
}, 0, frameDuration)
I cannot stop the MediaMuxer anymore. When I try to stop it, it get
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.tolotra.screenrecordexample, PID: 31248
java.lang.IllegalStateException: Failed to stop the muxer
at android.media.MediaMuxer.nativeStop(Native Method)
at android.media.MediaMuxer.stop(MediaMuxer.java:454)
at com.tolotra.screen_recorder.VideoBuilder._cleanUp(VideoBuilder.kt:292)
at com.tolotra.screen_recorder.VideoBuilder.finish(VideoBuilder.kt:95)
at com.tolotra.screen_recorder.ScreenRecorder$stop$1.run(ScreenRecorder.kt:156)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6734)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
After digging, I read somewhere
OpenGL always operates on a context that is made "current" and the context holds data in thread-local storage. This means it's thread-specific. Therefore you always need to be aware from which thread you're calling the OpenGL functions.
So I suspect that the problem is that my timer is the issue because it creates a new thread every time.
If my suspicion is true, how to I make this work with a timer ?
The solution is to Run the OpenGL/MediaMuxer/MediaEncoder setup/start/stop and timer callback on the same thread. This is achieved using single threaded executor
And in the timer