0

我正在尝试制作一个通过互联网广播视频的应用程序,目前我正在使用已弃用的 Camera API,将 Camera.PreviewCallback 添加到 Camera 对象,然后发送来自 Camera.PreviewCallback 的 onPreviewFrame() 方法中的字节数组.

但现在我想测试新的 Camera2 API,我正在看Camera2BasicTutorial,我认为我需要制作一个 CameraCaptureSession.CaptureCallback 对象来获取图像字节数组,就像教程说的那样:

CameraCaptureSession.CaptureCallback CaptureCallback
                = new CameraCaptureSession.CaptureCallback() {

            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                           @NonNull CaptureRequest request,
                                           @NonNull TotalCaptureResult result) {
                showToast("Saved: " + mFile);
                Log.d(TAG, mFile.toString());
                unlockFocus();


            }
        };

然后将其添加到 CameraCaptureSession:

mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);

问题是我不知道如何从 CaptureCallback 的 onCaptureCompleted() 中的任何参数中检索每个图像字节数组。

有什么帮助吗?

4

2 回答 2

0

你是对的 - 你无法从该onCaptureCompleted()方法中获取图像数据。该回调仅返回有关您自己簿记的曝光的元数据。实际的图像信息会发送到Surface您在曝光中指定的任何内容CaptureRequest

于 2015-10-05T20:47:13.097 回答
0

至少我意识到如何做我想做的事,从Camera2BasicTutorial,我对 Camera2BasicFragment 类做了以下更改:

  1. 修改 captureStillPicture() 方法以删除我认为对我的广播需求不必要的内容,也不允许此方法停止重复模式:

    private void captureStillPicture() {
    try {
        final Activity activity = getActivity();
        if (null == activity || null == mCameraDevice) {
            return;
        }
    
        final CaptureRequest.Builder captureBuilder =
                mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(mImageReader.getSurface());
    
        CameraCaptureSession.CaptureCallback CaptureCallback
                = new CameraCaptureSession.CaptureCallback() {
    
            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                           @NonNull CaptureRequest request,
                                           @NonNull TotalCaptureResult result) {
            }
        };
    
        mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
    }
    
  2. 在 createCameraPreviewSession() 方法中,禁用自动全闪:

    // When the session is ready, we start displaying the preview.
                        mCaptureSession = cameraCaptureSession;
                        try {
                            // Auto focus should be continuous for camera preview.
                            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                            // Flash is automatically enabled when necessary.
    // mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
    // CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
    
                            // Finally, we start displaying the camera preview.
                            mPreviewRequest = mPreviewRequestBuilder.build();
                            mCaptureSession.setRepeatingRequest(mPreviewRequest,
                                    mCaptureCallback, mBackgroundHandler);
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        }
    
  3. 我创建了一个布尔变量来检测当前是否正在处理图像,而不是将相机捕获的所有帧排队;另一个布尔值来跟踪是否有通过互联网发送的帧:

    private boolean mWorking = false;
    private boolean mNetworkWorking = false;
    
  4. 修改 CaptureCallback 对象以在每一帧中运行 captureStillPicture() 方法(仅当此时没有帧处理时)。

                case STATE_PREVIEW: {
    
                if (!mWorking){
                    Log.d(TAG, "capturing..");
                    mWorking = true;
    
                    mBackgroundHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            captureStillPicture();
                        }
                    });
    
                } else {
                    Log.d(TAG, "thread working, doing nothing");
                }
    
    
                break;
    
  5. 最后,读取帧并发送;我通过修改 OnImageAvailableListener 对象实现了这一点:

    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
        = new ImageReader.OnImageAvailableListener() {
    
    @Override
    public void onImageAvailable(final ImageReader reader) {
    
        // Process the image.
        Image image = reader.acquireNextImage();
        ByteBuffer buffer = image.getPlanes()[0].getBuffer();
        final byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        image.close();
    
        if (!mNetworkWorking){
            Thread thread = new Thread(){
                @Override
                public void run(){
    
                    mNetworkWorking = true;
    
                    HttpResponse response = null;
                    HttpClient client = new DefaultHttpClient();
                    HttpPost post = new HttpPost(mBroadcastUrl);
                    post.setEntity(new ByteArrayEntity(bytes));
    
                    try {
                        response = client.execute(post);
                    } catch (ClientProtocolException e) {
                        if (BuildConfig.LOCAL_LOG)
                            Log.w(TAG, "ClientProtocolException: "+e.getMessage());
                    } catch (IOException e) {
                        if (BuildConfig.LOCAL_LOG)
                            Log.w(TAG, "IOException: "+e.getMessage());
                    }
    
                    mNetworkWorking = false;
    
                }
            };
    
            thread.setName("networkThread");
            thread.setPriority(Thread.MAX_PRIORITY);
            thread.start();
        }
    
        mWorking = false;
    
    }
    
    };
    

就这样。

于 2015-10-29T10:08:01.093 回答