断开并重新连接VideoCapture和ImageCapture对象时,缓冲队列出错

问题描述

在我的主要活动中,我使用片段将两个用例分开,分别是ImageCapture和VideoCapture。每个片段都有一个TextureView,CameraX API在其中设置预览和用例以及一个按钮,以开始录制或拍照。主要活动布局具有FragmentLayout来包含片段,并带有在两者之间切换的按钮。

当我尝试过快地在两个片段之间切换时发生错误。

E/BufferQueueProducer: [ImageReader-4608x3456f100m2-25122-3](this:0x756dff9000,id:31,api:4,p:25122,c:25122) connect: already connected (cur=4 req=4)
E/Legacy-CameraDevice-JNI: connectSurface: Unable to connect to surface,error Invalid argument (-22).
    LegacyCameraDevice_nativeConnectSurface: Error while configuring surface Invalid argument (-22).
E/AndroidRuntime: FATAL EXCEPTION: RequestThread-0
    Process: com.vid.poly,PID: 25122
    java.lang.UnsupportedOperationException: Unknown error -22
        at android.hardware.camera2.legacy.LegacyExceptionUtils.throwOnError(LegacyExceptionUtils.java:77)
        at android.hardware.camera2.legacy.LegacyCameraDevice.connectSurface(LegacyCameraDevice.java:702)
        at android.hardware.camera2.legacy.RequestThreadManager.configureOutputs(RequestThreadManager.java:414)
        at android.hardware.camera2.legacy.RequestThreadManager.-wrap0(Unknown Source:0)
        at android.hardware.camera2.legacy.RequestThreadManager$5.handleMessage(RequestThreadManager.java:721)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:164)
        at android.os.HandlerThread.run(HandlerThread.java:65)

我一直到处逛逛,发现了类似的问题,这些问题可以帮助我减少遇到的错误数量,但该问题似乎是我的应用程序特有的。我读到缓冲队列属于TextureView(我认为),它涉及设置用例。但是我有两个仅属于“图片”或“视频”的TextureViews,为什么仍然说它“已经连接”。在切换片段之前,我调用CameraX.unbindAll(),这样是否应该完全删除用例呢?

public class PictureFragment extends Fragment {

    private static final String TAG = "PictureFragment";
    private Preview preview;
    TextureView textureView;
    PreviewConfig pConfig;
    TextView textView = null;
    View view;

    public PictureFragment() {
        // Required empty public constructor
        Log.i(TAG,"The Picture fragment has started");
    }


    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        view = inflater.inflate(R.layout.fragment_picture,container,false);
        textView = view.findViewById(R.id.fragment_picture_text);
        textView.setText("This is from within the onCreateView function");
        textureView = view.findViewById(R.id.picture_texture);

        startCamera();
        setupPictures();



        return view;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        CameraX.unbindAll();
    }

    private void updateTransform() {
        Matrix mx = new Matrix();
        float w = textureView.getMeasuredWidth();
        float h = textureView.getMeasuredHeight();
        float cx = w / 2f;
        float cy = h / 2f;
        int rotationDgr;
        int rotation = (int) textureView.getRotation();

        switch (rotation) {
            case Surface.ROTATION_0:
                rotationDgr = 0;
                break;
            case Surface.ROTATION_90:
                rotationDgr = 90;
                break;
            case Surface.ROTATION_180:
                rotationDgr = 180;
                break;
            case Surface.ROTATION_270:
                rotationDgr = 270;
                break;
            default:
                return;
        }
        mx.postRotate((float) rotationDgr,cx,cy);
        textureView.setTransform(mx);
    }

    private void startCamera() {
        CameraX.unbindAll();
        Rational aspectRatio = new Rational(textureView.getWidth(),textureView.getHeight());
        Size screen = new Size(textureView.getWidth(),textureView.getHeight());
        pConfig = new PreviewConfig.Builder().setTargetAspectRatio(aspectRatio).setTargetResolution(screen).build();
    }

    private void setupPictures() {
        preview = new Preview(pConfig);
        preview.setOnPreviewOutputUpdateListener(new Preview.OnPreviewOutputUpdateListener() {
            @Override
            public void onUpdated(Preview.PreviewOutput output) {
                ViewGroup parent = (ViewGroup) textureView.getParent();
                parent.removeView(textureView);
                parent.addView(textureView);

                textureView.setSurfaceTexture(output.getSurfaceTexture());
                updateTransform();
            }
        });

        ImageCaptureConfig imageCaptureConfig = new ImageCaptureConfig.Builder().setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY).
                setTargetRotation(getActivity().getWindowManager().getDefaultDisplay().getRotation()).build();

        final ImageCapture imgCap = new ImageCapture(imageCaptureConfig);

         view.findViewById(R.id.snap_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                File imageOutputFile = createOutputFile(true);

                imgCap.takePicture(imageOutputFile,new ImageCapture.OnImageSavedListener() {
                    @Override
                    public void onImageSaved(@NonNull File file) {
                        String msg = "Pic capture at " + file.getAbsolutePath();
                        Toast.makeText(getActivity().getBaseContext(),msg,Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(@NonNull ImageCapture.UseCaseError useCaseError,@NonNull String message,@Nullable Throwable cause) {
                        String msg = "Pic Capture failed: " + message;
                        Toast.makeText(getActivity().getBaseContext(),Toast.LENGTH_SHORT).show();
                        if (cause != null) {
                            cause.printStackTrace();
                        }
                    }
                });

            }
        });
        CameraX.bindToLifecycle(this,preview,imgCap);
    }

    private File createOutputFile(boolean picture) {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String extension = picture ? ".jpg" : ".mp4";
        String imageFileName = "MP4_" + timeStamp + "_";
        File storageDir = new File("/storage/emulated/0/DCIM/Camera/");
        File outputFile = null;
        try {
            outputFile = File.createTempFile(
                    imageFileName,/* prefix */
                    extension,/* suffix */
                    storageDir      /* directory */
            );
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outputFile;
    }
}

VideoFragment类看起来与PictureFragment相同。我认为您可以使用两个PictureFragments复制问题。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...