这是我的问题,我目前无法在调用捕获后用Camera2API中的静态捕获图像填充3个Surface中的一个。我使用了Google Camera2入门(需要链接)来设置样板,因此这段代码中很大一部分看起来很熟悉。
Camera2 capture声明:
每个请求将生成一个CaptureResult并为一个或多个目标Surface生成新帧,使用CaptureRequest构建器的addTarget(Surface)方法设置。目标曲面(使用addTarget(Surface)设置)必须是创建此捕获会话时提供的曲面的子集。
好的Android,我会留下
// in order to use a surface they must be registered when creating the session
List<Surface> surfaces = new ArrayList<>(previewSurfaces); //size + 1
surfaces.addAll(displaySurfaces); // size + 1
surfaces.add(mImageReader.getSurface()); //size + 1
try {
mCameraDevice.createCaptureSession(surfaces, mCaptureSessionCallback , null);
...
然后这样做
// Add the display surfaces along with the internal image reader
captureBuilder.addTarget(mImageReader.getSurface());
for(Surface surface : this.displaySurfaces) {
captureBuilder.addTarget(surface); //theres only one
}
CaptureRequest captureRequest = captureBuilder.build();
mCaptureSession.capture(captureRequest, captureCallback, mBackgroundHandler);
此时,添加到请求的表面将传递给捕获方法将将相机缓冲区输出到所有曲面。但是,我只看到在displaySurfaces没有爱的情况下调用mImageReader的回调。
所以我开始调试调试器并注意到传递给捕获的请求有一组大小为2的输出,以及相机会话的内部输出大小(如果大小为3)(两者都是正确)。但是,显示表面没有显示任何内容。另一个表面显示预览,并且工作正常。
我检查过的事情: a)是的,视图是可见的,其表面已准备就绪 b)视图具有相机支持的分辨率,并已使用setFixedSize()
设置在这里发生了什么我觉得我错过了什么。救命啊!
EDIT1
以下是曲面的生成方式;
private SurfaceView getPreviewView(Context context) throws CameraAccessException {
// TODO set z overlay?
Size previewSize = mCameraController.determineLargestSize();
Log.d(LOG_TAG, "Setting preview dimensions to: \n" +
"width: " + Integer.toString(previewSize.getWidth()) + "\n" +
"height " + Integer.toString(previewSize.getHeight()));
SurfaceView view = new SurfaceView(context);
view.getHolder().addCallback(mPreviewViewCallback);
view.getHolder().setFixedSize(previewSize.getWidth(),previewSize.getHeight());
view.setOnTouchListener(mZoomFocusListener);
return view;
}
private SurfaceView getDisplayTile(Context context) throws CameraAccessException {
SurfaceView previewTile = new SurfaceView(context);
Size smallest = mCameraController.determineSmallestSize();
int width = smallest.getWidth();
int height = smallest.getHeight();
Log.d(LOG_TAG, "Setting display tile dimensions to: \n" +
"width: " + Integer.toString(smallest.getWidth()) + "\n" +
"height " + Integer.toString(smallest.getHeight()));
previewTile.getHolder().addCallback(mDisplayCallback);
previewTile.getHolder().setFixedSize(width,height);
previewTile.setZOrderMediaOverlay(true);
previewTile.getHolder().setFormat(PixelFormat.TRANSLUCENT);
previewTile.setBackgroundColor(Color.BLUE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width,height);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.addRule(RelativeLayout.ALIGN_PARENT_END);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params.setMargins(7,7,7,7);
previewTile.setLayoutParams(params);
return previewTile;
}
以下是我将它们整合在一起的方式
private void initViews(Context context) throws CameraAccessException {
mFrameLayout = new FrameLayout(context);
// Add the view for the camera preview
FrameLayout.LayoutParams surfaceParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
mPreviewView = this.getPreviewView(context);
mFrameLayout.addView(mPreviewView,surfaceParams);
// Add the preview tile to the layout
FrameLayout.LayoutParams displayParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
displayParams.gravity = Gravity.BOTTOM | Gravity.RIGHT;
RelativeLayout layout = new RelativeLayout(context);
mCapturedTile = this.getDisplayTile(context);
layout.addView(mCapturedTile);
mFrameLayout.addView(layout, displayParams);
}
这里是未预览运行时应用的屏幕截图。我将右下方的框颜色为蓝色,即未显示相机输出的显示表面。
我还附加了Logcat,以便了解发生的事情
12-19 16:00:33.185 29863-29863/ngc.com.camera2app I/CameraController: This device has 2 available cameras
12-19 16:00:33.202 29863-29863/ngc.com.camera2app D/CameraController: Retrieveing current crop region
12-19 16:00:33.206 29863-29863/ngc.com.camera2app D/CameraView: Setting preview dimensions to:
width: 3264
height 2448
12-19 16:00:33.208 29863-29863/ngc.com.camera2app D/CameraView: Setting display tile dimensions to:
width: 176
height 144
12-19 16:00:33.948 29863-29863/ngc.com.camera2app D/CameraView: Surface created
12-19 16:00:33.949 29863-29863/ngc.com.camera2app D/CameraView: preview surface changed dimensions are
12-19 16:00:33.950 29863-29863/ngc.com.camera2app D/CameraView: width : 3264 | height : 2448
12-19 16:00:33.964 29863-29863/ngc.com.camera2app D/CameraView: Surface created
12-19 16:00:33.964 29863-29863/ngc.com.camera2app D/CameraView: display surface changed dimensions are
12-19 16:00:33.964 29863-29863/ngc.com.camera2app D/CameraView: width : 176 | height : 144
12-19 16:00:33.973 29863-29863/ngc.com.camera2app I/CameraController: Attempting to open camera
12-19 16:00:34.048 29863-29929/ngc.com.camera2app I/CameraController: Camera 0 is open for business
12-19 16:00:34.055 29863-29863/ngc.com.camera2app W/PathParser: Points are too far apart 4.000000596046461
12-19 16:00:34.065 29863-29929/ngc.com.camera2app D/CameraView: Camera ready
12-19 16:00:48.343 29863-29929/ngc.com.camera2app I/CameraController: Image available
我仍然坚持并且想要解决这个明显微妙的复杂错误并简单地从ImageReader的回调中加载图像。但是,如果API说它可以做到,那为什么不这样做!!
EDIT2
当来自曲面的两个回调都通过onChanged()
时,会调用此方法private synchronized void openCamera(){
if(displayReady && previewReady){
try {
List<Surface> displaySurfaces = new ArrayList<>();
//uncommenting this line adds a nasty bug
displaySurfaces.add(mPreviewView.getHolder().getSurface());
List<Surface> previewSurfaces = new ArrayList<>();
previewSurfaces.add(mCapturedTile.getHolder().getSurface());
mCameraController.openCamera(displaySurfaces, previewSurfaces);
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
EDIT3 将两个显示的分辨率更改为相同,结果相同。 SystemUI变得非常扭曲(ontop上的通知栏在整个屏幕上重复,底部软按钮移动到屏幕中间,非常奇怪)。我试图拍摄这种行为,但这就是我得到的
请注意,上面的屏幕截图不是UI为我显示的内容。此外,在应用程序关闭并重新启动后,预览屏幕的一半为绿色(再次,无法通过屏幕截图捕获此内容)。有什么想法吗?我开始认为Camera2 API有一个bug,但是,我也开始认为需要在这些表面上设置一些配置。不知道为什么奇怪的UI行为虽然......
答案 0 :(得分:1)
谢谢@EddyTalvala,原来这个问题是由于分辨率不匹配造成的。 PreviewSurface:3264 x 2446 DisplaySurface:176 X 148
我在中间遇到并将这两者的分辨率更改为640,480并解决了这个问题。