Android 摄像头预览的时候可以通过检测视频帧是否存在来判断是否有视频。在本文中,我将介绍如何在 Android 应用中实现摄像头预览,并通过代码示例演示如何检测视频帧的存在性。

1. 摄像头预览

在 Android 中,我们可以使用 Camera 或者 Camera2 API 来实现摄像头的预览。这里我们选择使用 Camera API 来进行示例演示。

首先,在 AndroidManifest.xml 文件中添加相机权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

然后,在布局文件中添加一个 SurfaceView 来显示摄像头预览:

<SurfaceView
    android:id="@+id/surfaceView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

接下来,在 Activity 或者 Fragment 中获取 Camera 实例,并将摄像头预览显示在 SurfaceView 上:

public class CameraPreviewActivity extends AppCompatActivity implements SurfaceHolder.Callback {

    private Camera mCamera;
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_preview);

        mSurfaceView = findViewById(R.id.surfaceView);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();
        try {
            mCamera.setPreviewDisplay(mSurfaceHolder);
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // 在此处进行摄像头预览的相关调整,例如设置预览尺寸等
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mCamera.stopPreview();
        mCamera.release();
    }
}

现在,我们已经实现了摄像头的预览功能。接下来,我们将介绍如何通过检测视频帧的存在来判断是否有视频。

2. 检测视频帧的存在

在摄像头预览时,我们可以通过 Camera.PreviewCallback 接口获取摄像头预览的帧数据。我们可以利用这个接口来判断视频帧是否存在。

首先,在 Camera.PreviewCallback 的回调方法中实现对视频帧的处理:

private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() {
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        // 在此处对视频帧进行处理
    }
};

然后,在 surfaceCreated 方法中设置 PreviewCallback:

@Override
public void surfaceCreated(SurfaceHolder holder) {
    mCamera = Camera.open();
    try {
        mCamera.setPreviewDisplay(mSurfaceHolder);
        mCamera.setPreviewCallback(mPreviewCallback); // 设置 PreviewCallback
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

现在,我们可以在 onPreviewFrame 方法中对视频帧进行处理。在这个方法中,我们可以将视频帧转换为 Bitmap,并检测是否有像素点的颜色值不为黑色来判断视频帧是否存在。

以下是一个简单的示例代码:

private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() {
    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        // 将视频帧转换为 Bitmap
        Camera.Size previewSize = camera.getParameters().getPreviewSize();
        YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, baos);
        byte[] jpegData = baos.toByteArray();
        Bitmap bitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length);

        // 检测视频帧的存在
        boolean hasVideo = false;
        for (int y = 0; y < bitmap.getHeight(); y++) {
            for (int x = 0; x < bitmap.getWidth(); x++) {
                int pixel = bitmap.getPixel(x, y);
                if (pixel != Color.BLACK) {
                    hasVideo = true;
                    break;
                }
            }
        }

        if (hasVideo) {
            Log.d("Camera