From e67d3b73d7e148d5e57ebe3fe3f5a5a309a27761 Mon Sep 17 00:00:00 2001 From: wang-bin Date: Mon, 26 Aug 2024 19:17:40 +0800 Subject: [PATCH] android: surface callback for impeller. fix #101 requires flutter 3.24 --- android/fvp_plugin.cpp | 8 ++-- .../java/com/mediadevkit/fvp/FvpPlugin.java | 37 +++++++++++++++---- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/android/fvp_plugin.cpp b/android/fvp_plugin.cpp index ab0daad..e7cdcbb 100644 --- a/android/fvp_plugin.cpp +++ b/android/fvp_plugin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 WangBin + * Copyright (c) 2023-2024 WangBin */ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -60,7 +60,7 @@ extern "C" JNIEXPORT void JNICALL Java_com_mediadevkit_fvp_FvpPlugin_nativeSetSurface(JNIEnv *env, jobject thiz, jlong player_handle, jlong tex_id, jobject surface, jint w, jint h, jboolean tunnel) { - if (!player_handle) { + if (!player_handle || !surface) { if (auto it = players.find(tex_id); it != players.end()) { auto& player = it->second; auto s = player->surface; @@ -69,13 +69,15 @@ Java_com_mediadevkit_fvp_FvpPlugin_nativeSetSurface(JNIEnv *env, jobject thiz, j if (s) { env->DeleteGlobalRef(surface); } + } else { + clog << "player not found(already removed?) for textureId " + std::to_string(tex_id) + " surface " + std::to_string((intptr_t)surface) << endl; } return; } assert(surface && "null surface"); auto player = make_shared(player_handle); clog << __func__ << endl; - if (tunnel) { + if (tunnel) { // TODO: tunel via ffi + global var player->surface = env->NewGlobalRef(surface); player->setProperty("video.decoder", "surface=" + std::to_string((intptr_t)player->surface)); } else { diff --git a/android/src/main/java/com/mediadevkit/fvp/FvpPlugin.java b/android/src/main/java/com/mediadevkit/fvp/FvpPlugin.java index b8ad0e9..7abc06f 100644 --- a/android/src/main/java/com/mediadevkit/fvp/FvpPlugin.java +++ b/android/src/main/java/com/mediadevkit/fvp/FvpPlugin.java @@ -26,7 +26,6 @@ import io.flutter.view.TextureRegistry.TextureEntry; import io.flutter.view.TextureRegistry.SurfaceTextureEntry; import io.flutter.view.TextureRegistry.SurfaceProducer; -// TODO: implement SurfaceProducer.Callback.onSurfaceCreated/onSurfaceDestroyed https://github.com/flutter/engine/pull/53280/files#diff-5029b9afc856679672880958cdebb729d04892b7ec8c80ebd649ef55fff744f3 /** FvpPlugin */ public class FvpPlugin implements FlutterPlugin, MethodCallHandler { @@ -71,23 +70,45 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { final boolean tunnel = (boolean)call.argument("tunnel"); TextureEntry te = null; Surface surface = null; - if (impeller) { - SurfaceProducer sp = texRegistry.createSurfaceProducer(); + final SurfaceProducer sp = impeller ? texRegistry.createSurfaceProducer() : null; + if (sp != null) { sp.setSize(width, height); surface = sp.getSurface(); te = sp; } else { SurfaceTextureEntry ste = texRegistry.createSurfaceTexture(); SurfaceTexture tex = ste.surfaceTexture(); - tex.setDefaultBufferSize(width, height); // TODO: size from player. rotate, fullscreen change? - surface = new Surface(tex); // TODO: when to release + tex.setDefaultBufferSize(width, height); + surface = new Surface(tex); te = ste; } - long texId = te.id(); + final long texId = te.id(); nativeSetSurface(handle, texId, surface, width, height, tunnel); textures.put(texId, te); surfaces.put(texId, surface); result.success(texId); + if (sp != null) { // FIXME: requires 3.24. how to build conditionally? + // 3.24: https://docs.flutter.dev/release/breaking-changes/android-surface-plugins + sp.setCallback( + new TextureRegistry.SurfaceProducer.Callback() { + @Override + public void onSurfaceCreated() { + Log.d("FvpPlugin", "SurfaceProducer.onSurfaceCreated for textureId " + texId); + final Surface newSurface = sp.getSurface(); + surfaces.put(texId, newSurface); + // will do nothing if same surface + nativeSetSurface(handle, texId, newSurface, width, height, tunnel); + } + + @Override + public void onSurfaceDestroyed() { + Log.d("FvpPlugin", "SurfaceProducer.onSurfaceDestroyed for textureId " + texId); + textures.remove(texId); + nativeSetSurface(handle, texId, null, 0, 0, tunnel); + } + } + ); + } } else if (call.method.equals("ReleaseRT")) { final int texId = call.argument("texture"); // 32bit int, 0, 1, 2 .... but SurfaceTexture.id() is long final long texId64 = texId; // MUST cast texId to long, otherwise remove() error @@ -99,10 +120,12 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { te.release(); } if (textures.remove(texId64) == null) { + Log.w("FvpPlugin", "onMethodCall: ReleaseRT texture not found for " + texId); } if (surfaces.remove(texId64) == null) { + Log.w("FvpPlugin", "onMethodCall: ReleaseRT surface not found for " + texId); } - Log.w("FvpPlugin", "onMethodCall: ReleaseRT texId: " + texId + ", surfaces: " + surfaces.size() + " textures: " + textures.size()); + Log.i("FvpPlugin", "onMethodCall: ReleaseRT texId: " + texId + ", surfaces: " + surfaces.size() + " textures: " + textures.size()); result.success(null); } else { result.notImplemented();