发送摄像头数据给c++
This commit is contained in:
@@ -17,7 +17,10 @@ import android.widget.FrameLayout;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.camera.core.AspectRatio;
|
||||||
import androidx.camera.core.CameraSelector;
|
import androidx.camera.core.CameraSelector;
|
||||||
|
import androidx.camera.core.ImageAnalysis;
|
||||||
|
import androidx.camera.core.ImageProxy;
|
||||||
import androidx.camera.core.Preview;
|
import androidx.camera.core.Preview;
|
||||||
import androidx.camera.core.SurfaceRequest;
|
import androidx.camera.core.SurfaceRequest;
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider;
|
import androidx.camera.lifecycle.ProcessCameraProvider;
|
||||||
@@ -26,38 +29,16 @@ import androidx.core.content.ContextCompat;
|
|||||||
|
|
||||||
import com.google.androidgamesdk.GameActivity;
|
import com.google.androidgamesdk.GameActivity;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
public class MainActivity extends GameActivity {
|
public class MainActivity extends GameActivity {
|
||||||
private TextureView textureView; // 使用 TextureView 替代 PreviewView
|
|
||||||
private ProcessCameraProvider cameraProvider;
|
private ProcessCameraProvider cameraProvider;
|
||||||
private FrameLayout containerLayout;
|
|
||||||
private void initCamera(){
|
private void initCamera(){
|
||||||
// 获取 GameActivity 的根视图
|
backgroundExecutor = Executors.newSingleThreadExecutor();
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
if (hasCameraPermission()) {
|
if (hasCameraPermission()) {
|
||||||
startCamera();
|
startCamera();
|
||||||
} else {
|
} else {
|
||||||
@@ -76,7 +57,7 @@ public class MainActivity extends GameActivity {
|
|||||||
}
|
}
|
||||||
String[] argArray = new String[2];
|
String[] argArray = new String[2];
|
||||||
argArray[0] = "sample";
|
argArray[0] = "sample";
|
||||||
argArray[1] = "hello_triangle";
|
argArray[1] = "texture_loading";//"hello_triangle";
|
||||||
sendArgumentsToPlatform(argArray);
|
sendArgumentsToPlatform(argArray);
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
@@ -97,6 +78,8 @@ public class MainActivity extends GameActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final int REQUEST_CAMERA_PERMISSION = 1001;
|
private static final int REQUEST_CAMERA_PERMISSION = 1001;
|
||||||
|
ImageAnalysis imageAnalyzer;
|
||||||
|
ExecutorService backgroundExecutor;
|
||||||
|
|
||||||
private void startCamera() {
|
private void startCamera() {
|
||||||
ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
|
ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
|
||||||
@@ -106,26 +89,32 @@ public class MainActivity extends GameActivity {
|
|||||||
try {
|
try {
|
||||||
cameraProvider = cameraProviderFuture.get();
|
cameraProvider = cameraProviderFuture.get();
|
||||||
|
|
||||||
Preview preview = new Preview.Builder().build();
|
|
||||||
|
|
||||||
CameraSelector cameraSelector = new CameraSelector.Builder()
|
CameraSelector cameraSelector = new CameraSelector.Builder()
|
||||||
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
|
.requireLensFacing(CameraSelector.LENS_FACING_FRONT)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// 使用 TextureView 的 SurfaceTexture
|
imageAnalyzer = new ImageAnalysis.Builder()
|
||||||
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
|
.setTargetAspectRatio(AspectRatio.RATIO_4_3)
|
||||||
if (surfaceTexture != null) {
|
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||||
Surface surface = new Surface(surfaceTexture);
|
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
|
||||||
preview.setSurfaceProvider(new Preview.SurfaceProvider() {
|
.build();
|
||||||
@Override
|
|
||||||
public void onSurfaceRequested(@NonNull SurfaceRequest request) {
|
|
||||||
request.provideSurface(surface, ContextCompat.getMainExecutor(MainActivity.this),
|
|
||||||
result -> {});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
Log.e("MainActivity", "Error starting camera: " + e.getMessage());
|
Log.e("MainActivity", "Error starting camera: " + e.getMessage());
|
||||||
@@ -133,6 +122,33 @@ public class MainActivity extends GameActivity {
|
|||||||
}, ContextCompat.getMainExecutor(this));
|
}, 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 int REQUEST_CODE_PERMISSIONS = 1001;
|
||||||
private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA};
|
private static final String[] REQUIRED_PERMISSIONS = new String[]{Manifest.permission.CAMERA};
|
||||||
|
|||||||
Reference in New Issue
Block a user