首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于预览和Camera2输入面的Android Camera2管道

用于预览和Camera2输入面的Android Camera2管道
EN

Stack Overflow用户
提问于 2020-05-26 09:27:54
回答 1查看 1.3K关注 0票数 2

我正在尝试将Android Camera2输出发送到预览界面和从MediaCodec.createInputSurface()获得的曲面。但是,当我将这些曲面传递给对CameraDevice.createCaptureSession的调用,然后尝试构建一个CaptureRequest时,我得到:

android.hardware.camera2.CameraAccessException:

CAMERA_ERROR (3):submitRequestList -不能使用未配置的曲面。

CaptureRequest构建逻辑(见下文)来自一个官方的颤振相机插件,当您使用MediaRecorder.getSurface()而不是MediaCodec.createInputSurface()时工作得很好。这意味着MediaCodec曲面还没有配置。我使用的是一个VideoEncoder类,它来自经过良好尝试的开放源代码RTMP代码(https://github.com/pedroSG94/rtmp-rtsp-stream-client-java),它与旧的Camera2(即不是Camera2)一起工作。该类初始化编解码器,因此:

代码语言:javascript
复制
   String type = CodecUtil.H264_MIME;
   MediaCodecInfo encoder = chooseEncoder(type);
    try {
      if (encoder != null) {
        codec = MediaCodec.createByCodecName(encoder.getName());
      } else {
        Log.e(TAG, "Valid encoder not found");
        return false;
      }
      MediaFormat videoFormat;
      //if you dont use mediacodec rotation you need swap width and height in rotation 90 or 270
      // for correct encoding resolution
      String resolution;
      if (!hardwareRotation && (rotation == 90 || rotation == 270)) {
        resolution = height + "x" + width;
        videoFormat = MediaFormat.createVideoFormat(type, height, width);
      } else {
        resolution = width + "x" + height;
        videoFormat = MediaFormat.createVideoFormat(type, width, height);
      }
      Log.i(TAG, "Prepare video info: " + this.formatVideoEncoder.name() + ", " + resolution);
      videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
          this.formatVideoEncoder.getFormatCodec());
      videoFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 0);
      videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
      videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, fps);
      videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
      if (hardwareRotation) {
        videoFormat.setInteger("rotation-degrees", rotation);
      }
      if (this.avcProfile > 0 && this.avcProfileLevel > 0) {
        // MediaFormat.KEY_PROFILE, API > 21
        videoFormat.setInteger("profile", this.avcProfile);
        // MediaFormat.KEY_LEVEL, API > 23
        videoFormat.setInteger("level", this.avcProfileLevel);
      }
      codec.configure(videoFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
      inputSurface = codec.createInputSurface();

当我试图构建捕获请求时失败的代码是在CameraCaptureSession.StateCallback.onConfigured,中,在这里,对build()的调用引发了异常:

代码语言:javascript
复制
createCaptureSession( CameraDevice.TEMPLATE_RECORD, successCallback, surfaceFromMediaCodec );

private void createCaptureSession(
        int templateType, Runnable onSuccessCallback, Surface... surfaces)
        throws CameraAccessException {

    // Close any existing capture session.
    closeCaptureSession();

    // Create a new capture builder.
    captureRequestBuilder = cameraDevice.createCaptureRequest(templateType);

    // Build Flutter surface to render to
    SurfaceTexture surfaceTexture = flutterTexture.surfaceTexture();
    surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
    Surface flutterSurface = new Surface(surfaceTexture);
    captureRequestBuilder.addTarget(flutterSurface);

    List<Surface> remainingSurfaces = Arrays.asList(surfaces);
    if (templateType != CameraDevice.TEMPLATE_PREVIEW) {
        // If it is not preview mode, add all surfaces as targets.
        for (Surface surface : remainingSurfaces) {
            captureRequestBuilder.addTarget(surface);
        }
    }

    // Prepare the callback
    CameraCaptureSession.StateCallback callback =
            new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    try {
                        if (cameraDevice == null) {
                            dartMessenger.send(
                                    DartMessenger.EventType.ERROR, "The camera was closed during configuration.");
                            return;
                        }
                        cameraCaptureSession = session;
                        captureRequestBuilder.set(
                                CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
                        cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null);
                        if (onSuccessCallback != null) {
                            onSuccessCallback.run();
                        }
                    } catch (CameraAccessException | IllegalStateException | IllegalArgumentException e) {
                        Log.i( TAG, "exception building capture session " + e );
                        dartMessenger.send(DartMessenger.EventType.ERROR, e.getMessage());
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                    dartMessenger.send(
                            DartMessenger.EventType.ERROR, "Failed to configure camera session.");
                }
            };

    // Collect all surfaces we want to render to.
    List<Surface> surfaceList = new ArrayList<>();
    surfaceList.add(flutterSurface);
    surfaceList.addAll(remainingSurfaces);
    // Start the session
    cameraDevice.createCaptureSession(surfaceList, callback, null);
}

如果我将MediaCodec inputSurface作为构建目标移除,它就能工作(但我不会将任何内容捕获到MediaCodec中)。我遗漏了什么?顺便说一句,在第二个代码提取中有一些颤振代码,但没有证据表明嵌入到颤振中是相关的。

EN

回答 1

Stack Overflow用户

发布于 2020-05-26 09:54:06

回答我自己的问题。我被误导的异常消息“不能使用未配置的表面”抛出了气味。表面被配置。我以为我查过尺寸了,但是一个是720x480,另一个是480x720。在我交换后就起作用了。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62018846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档