From 80ff2a091a2e49d8d33d11a497ed2d55e69484e9 Mon Sep 17 00:00:00 2001 From: Xiang Silian Date: Thu, 11 Sep 2025 14:20:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E9=80=81=E6=91=84=E5=83=8F=E5=A4=B4?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BB=99c++?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../khronos/vulkan_samples/MainActivity.java | 104 ++++++++++-------- 1 file changed, 60 insertions(+), 44 deletions(-) diff --git a/app/android/java/com/khronos/vulkan_samples/MainActivity.java b/app/android/java/com/khronos/vulkan_samples/MainActivity.java index 78adee6..dd15825 100644 --- a/app/android/java/com/khronos/vulkan_samples/MainActivity.java +++ b/app/android/java/com/khronos/vulkan_samples/MainActivity.java @@ -17,7 +17,10 @@ import android.widget.FrameLayout; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.camera.core.AspectRatio; import androidx.camera.core.CameraSelector; +import androidx.camera.core.ImageAnalysis; +import androidx.camera.core.ImageProxy; import androidx.camera.core.Preview; import androidx.camera.core.SurfaceRequest; import androidx.camera.lifecycle.ProcessCameraProvider; @@ -26,38 +29,16 @@ import androidx.core.content.ContextCompat; import com.google.androidgamesdk.GameActivity; import com.google.common.util.concurrent.ListenableFuture; + +import java.nio.ByteBuffer; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class MainActivity extends GameActivity { - private TextureView textureView; // 使用 TextureView 替代 PreviewView private ProcessCameraProvider cameraProvider; - private FrameLayout containerLayout; private void initCamera(){ - // 获取 GameActivity 的根视图 - ViewGroup rootView = (ViewGroup) getWindow().getDecorView(); - - // 创建容器布局 - containerLayout = new FrameLayout(this); - containerLayout.setLayoutParams(new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - )); - - // 创建 TextureView 用于摄像头预览 - textureView = new TextureView(this); - textureView.setLayoutParams(new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - )); - - // 将 TextureView 添加到容器 - containerLayout.addView(textureView); - - // 将容器添加到根视图的底部(作为背景) - //rootView.addView(containerLayout); // 添加到索引0(最底层) - rootView.addView(containerLayout, 0); - - + backgroundExecutor = Executors.newSingleThreadExecutor(); if (hasCameraPermission()) { startCamera(); } else { @@ -76,7 +57,7 @@ public class MainActivity extends GameActivity { } String[] argArray = new String[2]; argArray[0] = "sample"; - argArray[1] = "hello_triangle"; + argArray[1] = "texture_loading";//"hello_triangle"; sendArgumentsToPlatform(argArray); super.onCreate(savedInstanceState); @@ -97,6 +78,8 @@ public class MainActivity extends GameActivity { } private static final int REQUEST_CAMERA_PERMISSION = 1001; + ImageAnalysis imageAnalyzer; + ExecutorService backgroundExecutor; private void startCamera() { ListenableFuture cameraProviderFuture = @@ -106,26 +89,32 @@ public class MainActivity extends GameActivity { try { cameraProvider = cameraProviderFuture.get(); - Preview preview = new Preview.Builder().build(); - CameraSelector cameraSelector = new CameraSelector.Builder() - .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .requireLensFacing(CameraSelector.LENS_FACING_FRONT) .build(); - // 使用 TextureView 的 SurfaceTexture - SurfaceTexture surfaceTexture = textureView.getSurfaceTexture(); - if (surfaceTexture != null) { - Surface surface = new Surface(surfaceTexture); - preview.setSurfaceProvider(new Preview.SurfaceProvider() { - @Override - public void onSurfaceRequested(@NonNull SurfaceRequest request) { - request.provideSurface(surface, ContextCompat.getMainExecutor(MainActivity.this), - result -> {}); - } - }); - } + imageAnalyzer = new ImageAnalysis.Builder() + .setTargetAspectRatio(AspectRatio.RATIO_4_3) + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) + .build(); - cameraProvider.bindToLifecycle(this, cameraSelector, preview); + + imageAnalyzer.setAnalyzer(backgroundExecutor, new ImageAnalysis.Analyzer() { + + @Override + public void analyze(@NonNull ImageProxy image) { + try { + Log.d("Camera", "Received image: " + image.getWidth() + "x" + image.getHeight()); + processImageForVulkan(image); + } finally { + image.close(); // 确保在这里关闭 + Log.d("Camera", "Image closed, ready for next frame"); + } + } + }); + + cameraProvider.bindToLifecycle(this, cameraSelector, imageAnalyzer); } catch (ExecutionException | InterruptedException e) { Log.e("MainActivity", "Error starting camera: " + e.getMessage()); @@ -133,6 +122,33 @@ public class MainActivity extends GameActivity { }, ContextCompat.getMainExecutor(this)); } + private void processImageForVulkan(ImageProxy image) { + // 获取图像信息 + int width = image.getWidth(); + int height = image.getHeight(); + int format = image.getFormat(); + + // 获取图像数据平面 + ImageProxy.PlaneProxy[] planes = image.getPlanes(); + + // 对于 RGBA_8888 格式,通常只有一个平面 + if (planes.length > 0) { + ImageProxy.PlaneProxy plane = planes[0]; + ByteBuffer buffer = plane.getBuffer(); + int rowStride = plane.getRowStride(); + int pixelStride = plane.getPixelStride(); + + // 调用 Native 方法处理图像 + processImageNative(buffer, width, height, format, + rowStride, pixelStride, image.getImageInfo().getRotationDegrees()); + } + } + + // Native 方法 + private native void processImageNative(ByteBuffer buffer, int width, int height, + int format, int rowStride, int pixelStride, + int rotation); + private static final int REQUEST_CODE_PERMISSIONS = 1001; private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA};