-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
This is the same issue as #152839.
To recap, the SurfaceProducer API currently provides an onSurfaceDestroyed callback that is invoked after a surface has been destroyed. However, if the surface is being accessed by another thread, this is too late to do any cleanup as the thread may attempt to access the surface in between the call to cleanup() and the callback being invoked. Instead, we need a callback that is invoked before the call to cleanup() so that the rendering thread can be notified appropriately.
public void onTrimMemory(int level) {
if (!trimOnMemoryPressure) {
return;
}
if (level < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
return;
}
synchronized (lock) {
numTrims++;
}
// add callback.onSurfaceDestroying() here
cleanup();
// currently, surface could still be accessed from another thread here, but it is invalid
createNewReader = true;
if (this.callback != null) {
this.callback.onSurfaceDestroyed();
}
}This is the reason for the video_player package needing to destroy and recreate the entire player instance, as ExoPlayer will attempt to access the surface from the renderer thread after it has been destroyed, and go into an invalid state. This workaround is problematic as it breaks background playback, and results in the entire player state needing to be reloaded. This comment in the previous issue mentioned that it impossible to avoid this save/restore of the state, but this is not true since an onSurfaceDestroying callback would allow us to call player.setVideoSurface(null) on the ExoPlayer instance to ensure that it does not access the surface once it is destroyed, and allow playback to continue without a video surface.